package com.yupi.yupao.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yupi.yupao.common.ErrorCode;
import com.yupi.yupao.exception.BusinessException;
import com.yupi.yupao.model.domain.Team;
import com.yupi.yupao.model.domain.User;
import com.yupi.yupao.model.domain.UserTeam;
import com.yupi.yupao.model.domain.request.TeamJoinRequest;
import com.yupi.yupao.model.domain.request.TeamQuitRequest;
import com.yupi.yupao.model.domain.request.TeamUpdateRequest;
import com.yupi.yupao.model.dto.TeamQuery;
import com.yupi.yupao.model.enums.TeamStatusEnum;
import com.yupi.yupao.model.vo.TeamUserVO;
import com.yupi.yupao.model.vo.UserVO;
import com.yupi.yupao.service.TeamService;
import com.yupi.yupao.mapper.TeamMapper;
import com.yupi.yupao.service.UserService;
import com.yupi.yupao.service.UserTeamService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;

/**
* @author lenovo
* @description 针对表【team(队伍)】的数据库操作Service实现
* @createDate 2025-04-08 12:50:22
*/
@Service
public class TeamServiceImpl extends ServiceImpl<TeamMapper, Team>
    implements TeamService{


    @Resource
    private UserTeamService userTeamService;

    @Resource
    private UserService userService;
    /**
     * 创建队伍
     * @param team
     * @param lognUser
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long addTeam(Team team, User lognUser) {
        Long userId = lognUser.getId();
        // 校验参数是否合法
        if (team == null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍为空");
        }
        // 是否登录，未登录不允许创建
        if (lognUser == null){
            throw new BusinessException(ErrorCode.NOT_LOGIN);
        }
        // 队伍人数 >= 20
        Integer maxNum = Optional.ofNullable(team.getMaxNum()).orElse(0);
        if (maxNum < 1 || maxNum > 20){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍人数不能大于20");
        }
        // 队伍标题要小于等于20
        String name = team.getName();
        if (StringUtils.isBlank(name) || name.length() > 20){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍标题长度不能大于20");
        }
        // 队伍描述要小于等于512
        String description = team.getDescription();
        if (StringUtils.isBlank(description) && description.length() > 512){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍描述长度不能大于512个字符");
        }
        // 判断队伍的状态是否合法
        Integer status = Optional.ofNullable(team.getStatus()).orElse(0);
        TeamStatusEnum enumByValue = TeamStatusEnum.getEnumByValue(status);
        if (enumByValue == null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍状态不满足要求");
        }
        // 队伍的状态，是否加密
        if (TeamStatusEnum.SECRET.equals(status) && (StringUtils.isBlank(team.getPassword()) || team.getPassword().length() > 32)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "密码设置不正确");
        }
        // 超时时间大于等于当前时间
        Date expireTime = team.getExpireTime();
        if (new Date().after(expireTime)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "超时时间 > 当前时间");
        }
        // 校验用户最多创建5个队伍
        QueryWrapper<Team> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userId", userId);
        long count = this.count(queryWrapper);
        if (count > 5){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "一个用户最多创建5个队伍");
        }
        // 插入队伍信息到队伍表
        team.setId(null);
        team.setUserId(userId);
        boolean save = this.save(team);
        if (!save){
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "数据插入失败");
        }
        // 插入用户-队伍关系表
        UserTeam userTeam = new UserTeam();
        userTeam.setUserId(userId);
        userTeam.setTeamId(team.getId());
        userTeam.setJoinTime(new Date());
        boolean save1 = userTeamService.save(userTeam);
        if (!save1){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "创建队伍失败");
        }

        return team.getId();
    }

    /**
     * 查询队伍列表
     * @param teamQuery
     * @param isAdmin
     * @return
     */
    @Override
    public List<TeamUserVO> listTeams(TeamQuery teamQuery, boolean isAdmin) {
        QueryWrapper<Team> queryWrapper = new QueryWrapper<>();
        if (teamQuery != null){
            Long id = teamQuery.getId();
            String name = teamQuery.getName();
            String description = teamQuery.getDescription();
            Integer maxNum = teamQuery.getMaxNum();
            Long userId = teamQuery.getUserId();
            Integer status = teamQuery.getStatus();
            String searchText = teamQuery.getSearchText();
            if (StringUtils.isNotBlank(searchText)){
                queryWrapper.and(qw -> qw.like("name", searchText).or().like("description",searchText));
            }
            List<Long> idLst = teamQuery.getIdLst();
            if (CollectionUtils.isNotEmpty(idLst)){
                queryWrapper.in("id", idLst);
            }
            if (id != null && id > 0){
               queryWrapper.eq("id", id);
           }
           if (!StringUtils.isBlank(name)){
               queryWrapper.like("name", name);
           }
           if (StringUtils.isNoneBlank(description)){
               queryWrapper.like("description", description);
           }
           if (maxNum != null && maxNum > 0){
               queryWrapper.eq("maxNum", maxNum);
           }
           if (userId != null && userId > 0){
               queryWrapper.eq("userId", userId);
           }
            TeamStatusEnum enumByValue = TeamStatusEnum.getEnumByValue(status);
            if (!isAdmin && !enumByValue.equals(TeamStatusEnum.PRIVATE)){
                throw new BusinessException(ErrorCode.NO_AUTH);
           }
            if (status != null && status > -1){
                queryWrapper.eq("status", enumByValue.getValue());
            }
        }
        // 不展示已经过期的队伍
        queryWrapper.and(qw -> qw.gt("expireTime", new Date()).or().isNull("expireTime"));
        List<Team> teamList = this.list(queryWrapper);
        // 关联查询用户信息
        if (CollectionUtils.isEmpty(teamList)){
            return new ArrayList<>();
        }
        // 1、自己写Sql语句
        // 查询队伍和创建人信息
        // 关联查询创建人的用户信息
        List<TeamUserVO> teamUserVOList = new ArrayList<>();
        for (Team team : teamList) {
            Long userId = team.getUserId();
            if (userId == null){
                continue;
            }
            User user = userService.getById(userId);
            // 脱敏用户信息
            User safetyUser = userService.getSafetyUser(user);
            TeamUserVO teamUserVO = new TeamUserVO();
            BeanUtils.copyProperties(team, teamUserVO);
            UserVO userVO = new UserVO();
            BeanUtils.copyProperties(user, userVO);
            teamUserVO.setCreateUser(userVO);
            teamUserVOList.add(teamUserVO);
        }
        return teamUserVOList;
    }

    /**
     * 更新队伍
     * @param teamUpdateRequest
     * @return
     */
    @Override
    public boolean updateTeam(TeamUpdateRequest teamUpdateRequest, User loginUser) {
        if (teamUpdateRequest == null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Long id = teamUpdateRequest.getId();
        if (id == null || id <= 0){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Team oldTeam = this.getById(id);
        if (oldTeam == null){
            throw new BusinessException(ErrorCode.NULL_ERROR);
        }
        // 只有管理员和创建者才能修改队伍信息
        if (!oldTeam.getUserId().equals(loginUser.getId()) && !userService.isAdmin(loginUser)){
            throw new BusinessException(ErrorCode.NO_AUTH);
        }
        TeamStatusEnum enumByValue = TeamStatusEnum.getEnumByValue(teamUpdateRequest.getStatus());
        if (enumByValue.equals(TeamStatusEnum.SECRET)){
            if (StringUtils.isBlank(teamUpdateRequest.getPassword())){
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "加密的房间必须设置密码");
            }
        }
        Team updateTeam = new Team();
        BeanUtils.copyProperties(teamUpdateRequest, updateTeam);
        return this.updateById(updateTeam);
    }

    /**
     * 加入队伍
     * @param teamJoinRequest
     * @return
     */
    @Override
    public boolean joinTeam(TeamJoinRequest teamJoinRequest, User loginUser) {
        Long userId = loginUser.getId();
        QueryWrapper<UserTeam> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userId", userId);
        long count = userTeamService.count(queryWrapper);
        Long id = teamJoinRequest.getId();
        if (id == null || id <= 0){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Team team = this.getById(id);
        if (team == null){
            throw new BusinessException(ErrorCode.NULL_ERROR, "队伍不存在");
        }
        if (team.getExpireTime() != null && team.getExpireTime().before(new Date())){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍已经过期");
        }
        Integer status = team.getStatus();
        TeamStatusEnum enumByValue = TeamStatusEnum.getEnumByValue(status);
        if (enumByValue.equals(TeamStatusEnum.PRIVATE)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "禁止加入私有的队伍");
        }
        String password = teamJoinRequest.getPassword();
       if (enumByValue.equals(TeamStatusEnum.SECRET)){
           if (StringUtils.isBlank(password) || !password.equals(team.getPassword())){
               throw new BusinessException(ErrorCode.PARAMS_ERROR, "密码错误");
           }
       }
       synchronized (String.valueOf(userId).intern()){
           if (count > 5){
               throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户最多加入5个队伍");
           }
           queryWrapper = new QueryWrapper<>();
           queryWrapper.eq("teamId", id);
           queryWrapper.eq("userId", userId);
           long count2 = userTeamService.count(queryWrapper);
           // 不能重复加入队伍
           if (count2 > 0){
               throw new BusinessException(ErrorCode.PARAMS_ERROR, "不能重复加入队伍");
           }
       }
       synchronized (this) {
           // 已经加入队伍的人数
           long count1 = getTeamUserCountByTeamId(id);
           if (count1 >= team.getMaxNum()){
               throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍已经满了");
           }
           // 修改队伍信息
           UserTeam userTeam = new UserTeam();
           userTeam.setUserId(userId);
           userTeam.setTeamId(id);
           userTeam.setJoinTime(new Date());
           return userTeamService.save(userTeam);
       }
    }

    /**
     * 推出队伍
     * @param teamQuitRequest
     * @param loginUser
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean quitTeam(TeamQuitRequest teamQuitRequest, User loginUser) {
        if (teamQuitRequest == null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Long id = teamQuitRequest.getId();
        if (id == null || id <= 0){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Team team = this.getById(id);
        if (team == null){
            throw new BusinessException(ErrorCode.NULL_ERROR);
        }
        Long userId = loginUser.getId();
        UserTeam queryUserTeam = new UserTeam();
        queryUserTeam.setUserId(userId);
        queryUserTeam.setTeamId(id);
        QueryWrapper<UserTeam> queryWrapper = new QueryWrapper<>(queryUserTeam);
        long count = userTeamService.count(queryWrapper);
        if (count == 0){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "未加入队伍");
        }
        long teamUserCountByTeamId = this.getTeamUserCountByTeamId(id);
        // 队伍只剩下一个人，解散
        if (teamUserCountByTeamId == 1){
            // 删除队伍和所有加入队伍的关系
            this.removeById(id);
            QueryWrapper<UserTeam> userTeamQueryWrapper = new QueryWrapper<>();
            userTeamQueryWrapper.eq("teamId", id);
            return userTeamService.remove(userTeamQueryWrapper);
        }else {
            // 是否是队长
            if (team.getUserId().equals(userId)){
                // 把队伍转移给最早加入的用户
                QueryWrapper<UserTeam> queryWrapper1 = new QueryWrapper<>();
                queryWrapper1.eq("teamId", id);
                queryWrapper1.last("order by id acs limit 2");
                List<UserTeam> userTeamList = userTeamService.list(queryWrapper1);
                UserTeam nextUserTeam = userTeamList.get(1);
                if (CollectionUtils.isEmpty(userTeamList) || userTeamList.size() <= 1){
                    throw new BusinessException(ErrorCode.SYSTEM_ERROR);
                }
                Long userTeamUserId = nextUserTeam.getUserId();
                Team updateTeam = new Team();
                updateTeam.setId(id);
                updateTeam.setUserId(userTeamUserId);
                boolean b = this.updateById(updateTeam);
                if (!b){
                    throw new BusinessException(ErrorCode.SYSTEM_ERROR, "更新队长失败");
                }
                // 移除关系
            } // 不是队长

            return userTeamService.remove(queryWrapper);
        }
    }

    /**
     * 解散队伍
     * @param id
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delTeam(Long id, User loginUser) {
        if (id == null || id <= 0){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Team team = this.getById(id);
        if (team == null){
            throw new BusinessException(ErrorCode.NULL_ERROR);
        }
        if (!team.getUserId().equals(loginUser.getId())){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "无权限");
        }
        // 移除所有加入队伍的用户关联信息
        QueryWrapper<UserTeam> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("teamId", team.getId());
        boolean remove = userTeamService.remove(queryWrapper);
        if (!remove){
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "删除队伍关联信息失败");
        }
        // 删除队伍
        return this.removeById(team.getId());
    }

    /**
     * 获取队伍当前的人数
     * @param teamId
     * @return
     */
    private long getTeamUserCountByTeamId(Long teamId){
        QueryWrapper<UserTeam> userTeamQueryWrapper = new QueryWrapper<>();
        userTeamQueryWrapper.eq("teamId", teamId);
        return userTeamService.count(userTeamQueryWrapper);
    }
}